-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Naming conventions for syntax scopes #564
base: master
Are you sure you want to change the base?
Conversation
2021-02-01: This is now ready for review.To preview the changes brought by the PRs, follow this procedure: # Create a directory to host the PRs
mkdir naming-conventions
cd naming-conventions
# Install the PRs
for grammar in language-c language-css language-go language-html language-javascript language-python language-ruby; do
git clone --depth 1 --branch scopes https://github.com/chbk/$grammar.git
cd $grammar
apm install
cd ..
done
# Add the PRs to Atom
for grammar in language-c language-css language-go language-html language-javascript language-python language-ruby; do
apm link $grammar
done To remove the PRs from Atom: cd naming-conventions
for grammar in language-c language-css language-go language-html language-javascript language-python language-ruby; do
apm unlink $grammar
done |
Awesome man, doing god's work! As an aside, I'm wondering if we could add a repository that contains complete code snippets of all (possible) programming languages, covering the full range of available syntax. This would be a boon to syntax-theme developers, even if the syntax-scopes were a moving target. |
That would be nice, although covering every programming language would be tedious. I'm actually creating snippets to test the grammars listed above and I intend to include them in upcoming pull requests. If you want to create a central repository for code snippets I'd be glad to contribute mine. Another valuable resource for theme developers is the syntax theme template, which should be updated once the conventions are stable. Ideally, just a couple tweaks to the template should produce the desired coloring consistently across every language. That means a developer would only need to test his theme in a couple languages to be confident it works the same way in every language. |
Many of the challenges with existing Textmate scopes are the problems of gray areas. For example consider the 'variadic sizeof' in C++ which is Atom can theoretically handle these things quite well because of its use of CSS scopes which don't care about ordering. For example having both a My question here is; do you want to make a standard for all TextMate implementations, or is it okay if we take advantage of Atom's implementation? |
To ensure this standard never has the issue of the original Textmate standard I think it should be worded as if/case statements. For example:
Even this small example exposes the ambiguity of punctuation not being able to be used as variable names, and calls into question the difference between punctuation and keywords. There is a well defined difference, but the current standard doesn't make the difference clear. (I'll address this more when I discuss specific criticisms). |
Something to consider (I haven't seen it mentioned yet in any of the PR's), is releasing all the language and theme changes as a bundled extension to get feedback. Then after some time and feedback it can be made the default, and all the old language-scopes and themes can be bundled into a "legacy scoping" extension for those who really want the old style. It's just pretty awful when crunching to meet deadlines, and then an auto-update suddenly makes you feel blind because the colors have all changed. While on the other hand, people looking for an extension like this will be elated when they find something that does a better job at highlighting across the board. |
I'll clarify the context of this PR and hopefully that will answer your question. This documentation proposal is based on the Textmate naming conventions because that's what themes and grammars use, for lack of a suitable alternative. Atom defines itself as a hackable editor, yet creating a theme/grammar that's interoperable with other themes/grammars is too laborious: the Textmate scopes are insufficient and there is no Atom documentation. Recently, Atom adopted Tree-sitter to parse source code. It works great and surpasses regex parsers in many ways: it's smarter, faster, robuster. For end users to truly appreciate this change though, we need to bridge the gap between the parser and the interface, with extensive naming conventions for grammar and theme developers. This is where this PR comes in. Its goal is to correct and extend the Textmate conventions to make something practical for Atom. Once a clear set of conventions is endorsed and implemented, other editors that want to switch to Tree-sitter can fork the Atom grammars and benefit from them. In the long run, it's a win for everyone.
Taking specific examples to see how they fit in is a good way to validate the documentation. The
Scopes that are compatible with others are indicated in brackets in the documentation proposal.
I'll argue that the conventions can already be read as a series of conditions: if a definition fits your token, apply the scope. There are several benefits to presenting them as a list: it avoids complicated nesting of if/else statements, authorized overlaps are explicitly indicated in brackets, it's easier to skim through to find a fitting scope, and the main scopes can be highlighted to stand out.
Good point, although bundling all the themes and grammars in a single package might not be feasible. I'll add some instructions in the main post for those who want to preview the PRs. |
Browsing themes yesterday, I found Styri and thought I recognized the profile picture. Nice job I like it 😁 👍 So after reading your post, I'm thinking the answer is yes (answer to "can we take advantage of Atom's [e.g. TreeSitter] implementation"). Is that okay / a correct assumption? Because of this you can completely forget about my comment about an if-statement hierarchy. That was only under the assumption that TextMate scopes were going to be used. You'll be happy to hear I'm very familiar with the Tree Sitter and TextMate! I was actually the first to get the Tree sitter working cross platform in a VS Code extension (using Max Brunsfield's WASM build). That extension works terribly btw, but Max's work is amazing.
Just create an empty extension that lists all the language & theme extensions as dependencies! 👍 (assuming you've published the themes/languages as individual extensions) I learned that trick last week. I'm happy to help out in doing that. I just published a language-javascript extension last week (because the
These seem to conflict with each other, BUT hear me out. Say I want all my variables bold and I want all my functions blue. int i_should_be_bold = 10;
void i_should_be_blue() {};
auto i_should_be_bold_AND_blue = [ ]() -> int { return 10; }; I have an Atom theme that styles them correctly AND does not make a mutually-exclusive distinction. In fact I can ONLY style the third case correctly because they are allowed to overlap. I fully agree with "if a definition fits your token, apply the scope" 👍 and I think that statement should be the foundation for the entire standard. The statement never causes a conflict with itself, it is easy to remember, and it can be applied to any language concept including concepts that have yet to be invented! Following that logic, since a lambda meets the definition of both a variable and a function, both scopes are applied. Not to say that any hierarchy is bad, but any strictly-hierarchical implementation is going to be fundamentally flawed just like TextMate scopes. The Tree Sitter deserves a better standard. I think you and I are on the same page in that: the standard should define what happens when there is a conflict (such as variables=red, functions=blue). In that case, I think we can both agree the Sizeof...
Haha you'd think that, but actually the specification defines it as a single operator "Variadic templates use the (I maintain the C++ Textmate grammar for VS Code so I've spent an ungodly amount of time on these things). Not only is the While there is no C++ is quite convoluted haha. The tree sitter is just making a benign mistake. String literals
Ruby has both immutable and mutable strings so the string itself isn't really inherently constant, even Ruby's number literals can be mutable! Javascript can actually redefine Once upon a time, I thought Calling all literals In a similar vein, regex has true conditional statements which should be scoped as control flow. However, regex anchors do not control flow (and I believe they shouldn't be scoped as control flow). To make it easier on themes, the tools available in less (the less language) can be used to create fallbacks. If no style is given for regex anchors, then they can fallback on using the style given to the control flow scope. But that doesn't mean regex anchors should be scoped with an obviously incorrect scope. Just imagine if HTML tags used I really believe we can make a standard where there are no major/true |
Yes I don't see why not let others use it.
That's great! I think VS Code would benefit a lot from Tree-sitter as well.
Nice! I'll try that out.
It's something to aim for. The conventions should settle the ambiguities so developers don't struggle with them. There's a consensus to reach between languages so developers can achieve consistent highlighting within and across them.
I disagree with this. I'd rather add a
You can write
Thanks for pointing that out, I'll change the scope to
I agree with you, having a
I used this as a reference for the documentation but I'm open to suggestions for better scopes. |
I think
That is a global constant mutable lambda haha. In which case I still think it deserves both the constant and lambda tags. I'm fine with things like meta, that don't really make sense but can be reused from convention. And For numbers and strings I would be fine with .constant, except that constant already has a meaning (like in my example above). π, e, MAX_INT_SIZE are regarded constants by both programmers and mathematicians, and essentially nobody ever refers to a literal as "that constant". What if you (a theme maker) want to tag all literals but not constants? You'd have to do constant:not(every-single-possible-scope-for-a-literal) While there could be an additional ".literal" so that
Okay I'll take a look at it and see what I can come up with 👍 Before I plan specific suggestions though, I'm curious about the final verdict on "if it meets the definition, add it". Specifically the code example above where |
Different languages call similar things in different ways, there's a lot of diversity. The conventions just reach a consensus: tokens that are "constant", "final", "read-only", etc. are scoped
The conventions are a tree, so simply pick the branch whose definition fits your token. Overlaps are explicitly stated in brackets, they can be read as extensions of the branch you pick. |
Immutable, although somewhat unusual, works for me in terms of consistency (kind of picking one of term in self VS this, or property VS attribute, or method VS member-function) How would you scope that lambda though?
I absolutely agree with the diversity, but I see additional diversity as making it more difficult for an effective hierarchy to exist. |
I wonder whether scoping a function as |
Understandable, not every edgecase should be directly covered in the standard. My intent was not solving this specific case but rather using it as an example of many situations with conflicting definitions. We can't really judge if it is "relevant" because it's not only for us. Mutability is very important in Elixir, and Rust. Things like Rusts "unsafe" could be the defining line for an banking system. Just blanket saying "___ doesn't matter" is a pretty bold statement. Language servers (not just the tree sitter) will also be using this same scoping standard, and they're going to have a lot more scopes describing variables and functions (async, safe/unsafe, pure/impure, thread-safe, signal-safe, exceptionless, capturing/non-capturing, const, constexpr, member/non-member, friend, public/private/protected, etc). Back on topic though: for another example of overlapping definitions, consider Haskell where the operators themselves are entities that are passed around as values, yet they are also still operators. Or consider the opposite case in Haskell, where functions can be used as infix operators when inside backticks: Definitions like Same with
My main point is; the current hierarchy isn't a partition. There are gray areas exactly like the existing Textmate guidelines. Once grammar makers/language-servers reach those gray areas, they're going to make up their own solution. Two people make their own solution and boom: competing naming conventions exist (no standard), themers will have to memorize them, grammar maintainers have to debate whose is better; and we are right back at square 1. The design of the standard should be capable of dealing with concepts for languages that haven't even been invented yet. TLDR; Lambda is a fix for the specific case where the definitions (of variable and function) overlap, but what about all the other possible overlaps? Style BleedingA second (more practical) issue is that the CSS classes don't support a hierarchy. For example styling To have the scopes function as an actual hierarchy and not "bleed" style into other parts of the heirarchy, the scopes for something
Which is a viable solution Non-conflicting language specific scopes could also be created such as
or
|
It sounds like you would like to scrap the current hierarchy for a flat list of scopes instead. I've given it some thought but ultimately it's best to keep this hierarchy, for a couple reasons. First, it guarantees that scopes from one category won't conflict with scopes from other categories. You can't scope something That said, I welcome your insights on ambiguities that aren't covered by this PR yet. Specifically for your example in Haskell, the |
Sorry, I don't mean to be so pessimistic. So far you've done a great job addressing the issues I bring up. Lots of your solutions are good answers I hadn't considered (which might be the case with the last two issues I brought up too). I'm bringing these up because breaking backwards compatibility is going to be painful. If the change doesn't fix everything now, I people are going to be really against doing a second breaking change. If the fix doesn't clearly address all the issues, I think people will be less on board about the changes. While I think a flat system would solve the problem, it would basically be a full re-write which isn't great. I'm open to a partitioned heirarchy. However, whichever system is picked, I don't think gray areas should be allowed. Okay back to the details
So you're saying the standard ensures that names don't end up in multiple places of the heirarchy? (Which would prevent the style "bleeding" problem) I'm a bit confused with the |
Note: If someone styles |
Yeah ensuring backward compatibility is tough, especially when there isn't a definite standard to work with besides the scarce Textmate conventions. I'm glad you're passionate about this and I value your input and suggestions for different approaches. I think the best way to understand the hierarchy is to check out the updated template theme stylesheet. It shows how to structure a theme by separating scopes into categories. The idea is that having a rule just for |
e56ca37
to
9e049d5
Compare
Thanks for the screenshots (and sorry I missed them in that other PR) If we can add a prefix to the scopes, this PR has my full support. And I'm happy to help add them, you've put in a ton of work already. Would you be okay with them being added? For example, lets say the prefix is
Becomes (and note: the
Instead of
Its not overly beautiful, but there are 5 really strong benefits
If/when this PR is merged, I'd like to open a git repo (you @chbk as owner) with the hierarchy in the Readme as an official standard. That was proposed additions to it can be done as PR, and we can refer other people to it. I'll link to it in the language grammars I maintain. |
Update of the default syntax themes to implement [naming conventions](atom/flight-manual.atom.io#564) for syntax scopes. Adds the [template](atom/apm#883) to each theme with custom colors, to accommodate the naming conventions. There should be no compatibility break with existing grammars. As naming conventions are implemented in more language grammars, their old specific stylesheets can be retired.
Nice, it's great if you can get these scopes into other grammar packages. I'm happy with anything that brings us a usable standard. Your prefix idea is feasible, however, the scopes documented in this PR really aren't that radically different from the TextMate scopes. You'll end up with a lot of BTW the majority of scopes here aren't mandatory, you can have a very functional grammar/theme using only the bold scopes. The other scopes are here to provide plenty of examples and can be used if needed. So another possibility would be to just add some of the bold scopes to grammar packages, and then later complete them and weed out the old irrelevant scopes. This would help themes that rely on the obsolete If you want to open a repo for this, go for it 👍 |
ab5ad11
to
c221186
Compare
d8dd73b
to
0078522
Compare
Motivations for this PR
The lack of documentation on syntax scopes has been an issue for many years and still hinders the progress of contributors who wish to create themes and grammar packages for Atom. An attempt at fixing this has been made in 2015 but hasn't evolved since.
To resolve this ongoing issue, I propose this documentation based on Textmate scopes. Most of the conventional scopes have been preserved for backwards-compatibility with existing themes. However, I have also introduced new scopes and removed redundant ones. This documentation aims to be:
Changes from the Textmate Scopes
(click items to expand)
Additions
keyword.storage.declaration
The
storage.type
scope is too general. The lack of specificity results in this scope being misused, e.g.let
scoped asstorage.type
in JavaScript, or just blatantly ignored, e.g.func
scoped askeyword.function
in Go orenum
scoped askeyword.control
in C. More specific scopes to differentiate variable type keywords from declaration keywords are needed. Keywords that declare an entity (union
,struct
,function
,def
,var
,mod
, etc.) are now scopedkeyword.storage.declaration
. Keywords that specify a variable's type are now scopedkeyword.type
.entity.type
Type highlighting must stay consistent across a document. Any identifier that can be used as a type must be scoped as such.
entity.type.support
This scope targets built-in types that aren't keywords. It also includes built-in class types such as
String
,List
,Exception
.entity.type.fundamental(.support)
More precise than
entity.type.support
, this scope targets fundamental primitive and compound types (int
,bool
,list
,map
, etc.) that aren't keywords.entity.operator
To stay coherent with the
keyword
scope, this scope is used in languages that support non-keyword operators.keyword.type
,keyword.variable
,keyword.function
The four main
entity
scopes (variable
,function
,operator
,type
) are given akeyword
equivalent for reserved tokens.symbolic
For themes that wish to target non-alphabetic tokens and highlight them the same way regardless of their more specific scopes.
punctuation
Punctuation is part of language grammars and must not be neglected.
text
Unformatted text in HTML and Markdown requires a scope as well.
markup
is specifically used for stylized text, atext
scope is needed to avoid leaving any tokens unscoped.string.part
To give more general control over string highlighting, this scope encompasses parts of strings such as interpolations, placeholders, format specifiers etc.
comment.part
Parts of comments worthy of highlighting such as captions and documented terms are also given a general scope.
More specific scopes
Every language has their own vocabulary, and that creates conflicts between scopes. Let's consider the
module
scope as an example. Depending on the language, a module can be a namespace (Rust), an imported package (Python), a mixin class (Ruby)... Themodule
scope becomes meaningless for syntax themes without the language context. We can resolve this by providing pre-defined scopes that call similar elements by the same name, regardless of the language. In this case, these scopes would benamespace
for a collection of entities,package
for an imported element, andclass.mixin
for a mixin class.Adjustments
entity
The original definition from the Textmate docs reads "An entity refers to a larger part of the document [...]. We do not scope the entire entity as entity.* (we use meta.* for that). But we do use entity.* for the placeholders in the larger entity [...]". This leads to
entity
being solely used to scope identifiers and re-used whenever the identifiers re-appear in the document. Hence, the practical definition forentity
is simply "an identifier".storage
This scope encompasses "Things relating to “storage”" according to the original Textmate documentation. This catch-all definition is useless for themes that want to differentiate declaration keywords, keyword types, support types, and other defined types. To resolve this ambiguity, this scope is now organized into different categories:
keyword.storage
for storage keywords,keyword.type
for non-redefinable keyword types,entity.type
for non-keyword types,entity.type.support
for built-in non-keyword types,entity.type.fundamental.support
for primitive and composite non-keyword types.support
Using this scope must not exempt one from also using other relevant scopes. Therefore
support
is no longer its own standalone category but is appendable to other scopes when appropriate. Furthermore, the original definition for this scope was "things provided by a framework or library". But in practice it is mostly used for built-in entities rather than imported ones. This justifies changing the definition to "a built-in or imported or conventional token that can usually be redefined".invalid
An invalid token can either be a deprecated token or an illegal token. Similarly to
support
, it must be used with other relevant scopes when applicable. Often these scopes would beentity
orkeyword
orpunctuation
.variable
A variable is an entity. Similarly to
support
it must not be used as a standalone scope. It is now nested under theentity
orkeyword
scopes and can be used along with more specific scopes such asparameter
,argument
,support
,member
, etc. which gives more control to themes to fine-tune their highlighting.Deletions
other
This scope is used too liberally and contributes no information.
name
inentity.name
Adding
name
toentity
is redundant as the latter is exclusively used to scope named elements.java
,python
, etc.Trailing scopes identifying the language are redundant as this information is provided by the root scope, e.g.
source.java
.Amendments to the Documentation
I propose adding the following section to the Hacking Atom chapter of the Atom flight manual. I use "class" instead of "scope" below to conform to the terminology used in existing documentation.
Syntax Naming Conventions
Naming conventions provide predefined names for similar tokens in different languages. These language-agnostic names, called syntax classes, help themes highlight code without relying on language-specific vocabulary.
When creating a language grammar, use these conventions to determine which syntax classes correspond to your syntax nodes. When creating a syntax theme, use these conventions to determine which syntax classes correspond to your theme colors.
Guidelines for Language Grammars
The syntax classes are organized into nested categories. In a language grammar, multiple nested classes can be applied to a syntax node by appending them with periods, as in
entity.function.call
. The order in which classes are appended does not affect the resulting highlighting. However, we recommend following their hierarchy to stay consistent.Root classes, like
▶ entity
, must not be appended to other root classes, unless explicitly allowed in this documentation. Main classes indicated in bold, likefunction
, must be used for coherent highlighting. Shared classes indicated in brackets, like[call]
, can be appended when relevant. You may create additional classes if they clarify your grammar and do not introduce conflicts with existing classes.Guidelines for Syntax Themes
In a syntax theme, styling can be applied to a syntax class with the
syntax--
prefix, as insyntax--entity
. When targeting a nested class, specify its parent classes by prepending them with periods, as insyntax--entity.syntax--function.syntax--call
. A typical styling rule would look like this:List of Syntax Classes
(click items to expand)
keyword
keyword
— A keyword.[symbolic]
— A keyword with no alphabetic characters.control
— A control or structure keyword.condition
— A condition keyword.Examples:
if
,else
,elif
.loop
— A loop keyword.Examples:
for
,for
...in
,for
...of
,do
,while
.exception
— An exception keyword.Examples:
try
,catch
,finally
.jump
— A keyword used to jump to/from a statement.Examples:
break
,continue
,pass
,return
,yield
,throw
,await
,defer
.package
— A keyword for imports or exports.Examples:
import
,from
,include
,export
,require
.directive
— An instruction given to the compiler.Examples:
#include
,#define
,#ifdef
,using
,package
,use strict
.evaluate
— A keyword used to evaluate an expression.Examples:
assert
,with
...as
.storage
— A storage keyword.modifier
— A keyword to detail the behavior of an entity.Examples:
static
,abstract
,final
,throws
,get
,extends
.declaration
— A keyword to declare an entity.Examples:
let
,const
,func
,def
,end
,class
,enum
,typedef
,namespace
.type
— A type keyword.Examples:
char
,int
,bool
,void
.wildcard
— A wildcard keyword for an unknown type.Example:
?
inList<?> list
.operator
— An operator keyword. Includes overloaded operators.logical
— A logical operator.Examples:
and
,not
,or
,!
,&&
,||
.ternary
— A ternary condition operator.Examples:
?
,:
.assignment
(compound)
— An assignment operator.Examples:
=
,:=
,+=
,-=
,*=
,%=
.comparison
— A comparison operator.Examples:
==
,<
,>
,!=
,in
,instanceof
.arithmetic
— An arithmetic operator.Examples;
+
,-
,/
,*
,@
,++
,--
.pointer
(reference)
(dereference)
— A pointer operator.Examples:
&
,*
.bitwise
— A bitwise operator.Examples:
<<
,>>
,|
,&
,^
,~
.instance
— A instance operator.Examples:
del
,delete
,new
,typeof
.composition
— A composition operator (Haskell).Example:
.
.combinator
— A combinator operator (CSS).Examples:
>
,+
,~
,&
.function
— A function keyword.Example:
super
.variable
— A variable keyword.Examples:
this
,self
,@
.entity
entity
— An identifier.[parameter]
— A parameter in a definition or declaration or call.Examples:
myFunction(parameter = argument)
,class MyClass<parameter> {}
.[argument]
— An argument in a call.Examples:
instance.method(argument)
,new MyClass(argument)
.[definition]
— An entity that is being defined or declared.Examples:
my_variable
inlet my_variable
,myFunction
indef myFunction()
.[call]
— An entity that is being called.Examples:
myFunction
inmyFunction(argument)
,MyClass
innew MyClass(argument)
.[mutable]
— An entity whose properties or value can be changed.Examples:
var mutable
,let mutable
.[immutable]
— An entity whose properties or value cannot be changed.Examples:
const immutable
,final immutable
.[support]
— A built-in or imported or conventional entity that can usually be redefined.Examples:
self
,cls
,arguments
,iota
,len
,print
,loop
,int
,list
,bool
.variable
— A variable.member
— A member variable in an object.Examples:
{property: value}
,object.attribute
.function
— A function.cast
— A type casting function that is not a type itself.Examples:
as.matrix()
,toInt()
.method
(constructor)
— A method in an object.Examples:
{method: (parameter) => value}
,object.method()
.lambda
— A lambda.Example:
lambda = ->() {}
.infix
— A function used in infix notation.Example:
1 `function` 2
.operator
— An operator.[symbolic]
— An operator with no alphabetic characters.Examples:
%>%
,<+>
.type
— A type.[cast]
— A type used for type casting, eventually in functional notation.Examples:
float(32)
,int(3.2)
,matrix()
.[constructor]
— A type used as an instance constructor, eventually in functional notation.Examples:
new MyClass()
.fundamental
— A fundamental primitive or composite type.Examples:
char
,int
,bool
,rune
,list
,map
,tuple
.class
— A class.Examples:
MyClass
,String
,List
.inherited
— An inherited class.Example:
class Child < Inherited
.mixin
— A mixin class.Example:
module Mixin
(Ruby).generic
— A generic class.Examples:
<T>
,<E>
.exception
— An exception.Example:
AssertionError
.abstract
— An abstract class.Example:
abstract class Abstract
(Java)interface
— An interface.Example:
Vehicle
inpublic interface Vehicle {}
.enumeration
— An enumeration.Example:
Color
inenum Color{red, green, blue}
.structure
— A structure.Examples:
Address
intype Address struct {}
.union
— An union.Example:
IPv4
inunion IPv4 {}
.alias
— An alias.Example:
Number
intypedef int Number
.annotation
— An annotation.Examples:
@Override
(Java),#[test]
(Rust),[Obsolete]
(C#).namespace
— A namespace.Examples:
namespace Namespace {}
(C++),namespace::function()
(Rust).package
— A package.Example:
from package import entity
.label
— A statement label.Example:
goto label
.lifetime
— A lifetime (Rust).Example:
'static
.tag
— A tag (HTML).Examples:
body
,div
,input
.attribute
(id)
(class)
— An attribute (HTML).Example:
<tag attribute=value>
.property
— A property (CSS).Example:
{property: value}
.selector
(tag)
(id)
(class)
(pseudo-...)
(attribute)
— A selector (CSS).Examples:
#id
,.class
,:hover
,:not
,::before
,::after
,[attribute]
.string
string
— A string or part of a string.[argument]
— An argument in a call.Examples:
myFunction("string")
,new MyClass('string')
.[mutable]
— A mutable string. Specified when mutable and immutable coexist.Example:
'string'
(Ruby).[immutable]
— An immutable string. Specified when mutable and immutable coexist.Example:
:immutable
(Ruby).[key]
— A key in a key-value pair.Example:
{"key" => value}
.[quoted]
— A quoted string.Examples:
"string"
,'string'
,$"template string"
,/^regexp string$/
.[unquoted]
— An unquoted string.Example:
'key': unquoted
.[part]
— A part of a string.interpolation
— An interpolation.Examples:
${variable}
,{variable:<30}
.placeholder
— A placeholder.Examples:
%()d
,{0:.2f}
,%-#10x
,\1
.format
— A format specifier.Examples:
<30
,d
,.2f
,-#10x
.regexp
— A regular expression.Example:
/^regexp$/
.[part]
— A part of a regular expression.language
— A regular expression keyword.[symbolic]
— A keyword with no alphabetic characters.control
(anchor)
(reference)
(mode)
— A control token.Examples:
^
,$
,\b
,\k
,\1
,i
in(?i)
,g
in/^regexp$/g
.operator
(quantifier)
— A quantifier operator.Examples;
?
,*
,+
,{1,2}
.variable
— A regular expression variable.Examples:
(?<variable>)
,\k<variable>
.group
— A regular expression group.Examples:
(capture)
,(?:non-capture)
.lookaround
— A regular expression lookaround.Example:
(?=lookahead)
.set
— A regular expression set.Example:
[^A-Z]
.template
— A template string.Examples:
$"string {interpolation}"
,`string ${interpolation}`
.heredoc
— A here document.Example:
<<EOF A multiline here document EOF
.constant
constant
— A literal other than a string.[argument]
— An argument in a call.Examples:
myFunction(constant)
,float(constant)
.[key]
— A key in a key-value pair.Example:
{key: value}
.[quoted]
— A quoted constant.Example:
'a'
.[unquoted]
— An unquoted constant.Example:
#color
.[support]
— A built-in or imported or conventional constant.Examples:
absolute
,blue
,screen
.[language]
— A literal keyword.[symbolic]
— A keyword with no alphabetic characters.Example:
...
(Python).boolean
— A boolean.Examples:
true
,false
.null
— A null value.Examples:
None
,null
,nil
.undefined
— An undefined value.Example:
undefined
.numeric
— A numeric word.Example:
Infinity
.numeric
— A number.integer
— An integer.Example:
2
.decimal
— A decimal number.Example:
.17
.hexadecimal
— A hexadecimal number.Example:
0x29
.unit
— A length unit (CSS).Examples:
%
,px
,pt
,em
.duration
— A duration (Lilypond).Examples:
8
,2.
.character
— A character.Example:
'a'
.[escape]
— An escape sequence.Examples:
\"
,\\
,\i
,\?
,\u2661
,\n
,\d
,\W
.code
— A substitute for another character.Examples:
<
,\x2f
,\n
.shorthand
— A shorthand for other characters (RegExp).Examples:
.
,\d
,\W
,\s
.range
— A range of characters (RegExp).Examples:
a-z
,0-9
.whitespace
— A whitespace character.Examples:
\t
,\f
.newline
— A newline character.Examples:
\n
,\r
.unicode
— A unicode code point.Example:
\u2661
.hexadecimal
— A hexadecimal code point.Example:
\x2f
.octal
— An octal code point.Example:
\143
.color
— A color (CSS).Examples:
crimson
,#a35
.prefix
— A color prefix.Example:
#
.font
— A font (CSS).Examples:
Helvetica
,Times New Roman
.style
— A style (CSS).Examples:
break-word
,solid
,absolute
.note
— A note (Lilypond).Examples:
c
,d'
,a,,
.rest
— A rest (Lilypond).Example:
r
.text
text
— Plain text (HTML, Markdown).markup
markup
— Stylized text (Markdown).heading
— A heading.Example:
# Heading
.list
— A list item.Examples:
1. item
,- item
.quote
— A quote.Example:
> quote
.bold
— Bold text.Example:
**bold**
.italic
— Italic text.Example:
*italic*
.underline
— Underlined text.Example:
__underline__
.strike
— Striked-through text.Example:
~~strike~~
.raw
— Raw unformatted text or code.Example:
`raw`
.link
— An url or path or reference.Examples:
url.com
,(path)
in[alt](path)
,[reference]
.alt
— Alternate text for a link.Examples:
[alt]
,![alt]
.critic
— A critic.inserted
— An insertion.Example:
{++ inserted ++}
.deleted
— A deletion.Example:
{-- deleted --}
.changed
— A modification.Example:
{~~ from ~> to ~~}
.commented
— A comment.Example:
{>> commented <<}
.highlighted
— A highlight.Example:
{== highlighted ==}
.comment
comment
— A comment or part of a comment. Includes comments in strings.Examples:
(?# comment)
,<!-- comment -->
,/* comment */
.[part]
— A part of a comment.caption
— A caption in a comment.Examples:
@param
,<returns>
,NOTE
,TODO
,FIXME
.path
— A path in a comment.Example:
path/to/my-file
.term
(variable)
(function)
(operator)
(type)
— A documented entity.Examples:
type
andvariable
in@param {type} variable
.line
— A one-line comment.Example:
# comment
.block
— A multi-line comment.Example:
/* ... */
.punctuation
punctuation
— A punctuation mark.definition
— Punctuation that defines tokens.string
— Punctuation for a string.Examples:
"
,'
,$"
.regexp
— Punctuation for a regular expression.Examples:
r"
,/
.constant
— Punctuation for a constant.character
— Punctuation for a character.Example:
'
.markup
— Punctuation for text styling (Markdown).Examples:
_
,*
,~
,#
,-
.1.
,[
,]
.comment
— Punctuation for a comment.Examples:
//
,#
,<!--
,-->
.collection
— Punctuation for a collection (array, set, map, etc.).Examples:
[
,]
,{
,}
.variable
— Punctuation for a variable.Example:
$
.function
(generator)
— Punctuation for a function.Examples:
`
,*
.operator
— Punctuation for an operator.Examples:
(
,)
.package
(wildcard)
— Punctuation for a package.Examples:
.
,*
.annotation
— Punctuation for an annotation.Examples:
@
(Java),#![]
(Rust).decorator
— Punctuation for a decorator.Example:
@
(Python).tag
— Punctuation for a tag (HTML).Examples:
<
,/>
.selector
(wildcard)
— Punctuation for a selector (CSS).Examples:
*
,.
,#
,:
,::
,[
,]
.operation
— Punctuation to operate on tokens.variadic
— Punctuation to operate on variadic arguments.Examples:
...
,*
,**
.return
— Punctuation to operate on lambda parameters.Example:
->
in(parameter) -> expression
.association
— Punctuation to associate values to tokens.pair
— Punctuation to associate an expression to a key.Examples:
:
inkey: value
,=>
inNone => println!("Nothing")
.iterator
— Punctuation to associate an expression to an iterator.Example:
:
inauto& iterator : items
.accessor
— Punctuation to access contained entities.member
— Punctuation for member access.Examples:
.
,->
.scope
— Punctuation for scope resolution.Example:
::
.delimiter
— Punctuation to delimit tokens.string
— Punctuation to delimit tokens in a string.[part]
— Punctuation to delimit a part of a string.interpolation
— Punctuation to delimit an interpolation.Examples:
#{
,${
,}
.placeholder
— Punctuation to delimit a placeholder.Examples:
{
,}
,%
,%(
,)
.format
— Punctuation to delimit a format specifier.Example:
:
.regexp
— Punctuation to delimit tokens in a regular expression.[part]
— Punctuation to delimit a part of a regular expression.group
— Punctuation to delimit a group.Examples:
(?:
,(
,(?P
,)
.lookaround
— Punctuation to delimit a lookaround.Examples:
(?=
,(?!
,)
.disjunction
— Punctuation to delimit a disjunction.Example:
|
.set
— Punctuation to delimit a set.Examples:
[^
,[
,]
.mode
— Punctuation to delimit a mode specifier.Examples:
(?
,)
.comment
— Punctuation to delimit tokens in a comment.[part]
— Punctuation to delimit a part of a comment.caption
— Punctuation to delimit a caption.Examples:
<
,>
,:
.term
— Punctuation to delimit a documented entity.Examples:
{
and}
in{type}
.parameters
— Punctuation to delimit parameters.Examples:
(
,)
.arguments
— Punctuation to delimit arguments.Examples:
(
,)
.subscript
— Punctuation to delimit a subscript.Examples:
[
,]
.type
— Punctuation to delimit a type or return type.Examples:
<
,:
,->
,(
,)
.body
— Punctuation to delimit a body.Examples:
{
,}
,:
.statement
— Punctuation to delimit a statement.Examples:
{
,}
,:
.expression
— Punctuation to delimit an expression.Examples:
(
,)
.embedded
— Punctuation to delimit embedded code.Examples:
~~~
,<%=
,%>
.package
— Punctuation to delimit package imports or exports.Examples:
(
)
,{
,}
.separator
— Punctuation to separate similar tokens.Examples:
,
,\
.terminator
— Punctuation to terminate a statement.Example:
;
.invalid
[invalid]
— An invalid token. Appendable to every class.deprecated
— A deprecated token which should no longer be used.illegal
— An illegal token which doesn't belong there.meta
meta
— A larger part of the document encompassing multiple tokens.function
— A function definition block.class
— A class definition block.embedded
— A language embedded in another.Related Pull Requests
The following themes and grammars are ready to be updated with the naming conventions. Screenshots showing the syntax highlighting improvements are attached in each PR.